﻿using Microsoft.WindowsAPICodePack.Dialogs;
using SearchInFiles.Global;
using SearchInFiles.Lib.Search;
using SearchInFiles.Lib.Tools;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SearchInFiles.Windows
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //界面绑定需要的元素-有效的编码格式列表
        public ObservableCollection<FileElements.EncodingData> EncodingValidCollection { get => (ObservableCollection<FileElements.EncodingData>)GetValue(EncodingValidCollectionProperty); set => SetValue(EncodingValidCollectionProperty, value); }
        public static readonly DependencyProperty EncodingValidCollectionProperty = DependencyProperty.Register("EncodingValidCollection", typeof(ObservableCollection<FileElements.EncodingData>),
            typeof(MainWindow), new PropertyMetadata(new ObservableCollection<FileElements.EncodingData>(FileElements.EncodingCollection.Where(p => p != FileElements.NotAvailableEncodingData).ToArray())));
        //搜索结果数据
        public ObservableCollection<SearchResult> SearchResults { get => (ObservableCollection<SearchResult>)GetValue(SearchResultsProperty); set => SetValue(SearchResultsProperty, value); }
        public static readonly DependencyProperty SearchResultsProperty = DependencyProperty.Register("SearchResults",
            typeof(ObservableCollection<SearchResult>), typeof(MainWindow), new PropertyMetadata(new ObservableCollection<SearchResult>()));

        private CancellationTokenSource? cancellationTokenSource;

        public MainWindow() { InitializeComponent(); }
        private bool IsCompleteMatch => CompleteMatchButton.IsChecked == true ? true : false;
        private bool IsAllMatch => AllMatchButton.IsChecked == true ? true : false;

        //状态栏-调用-启动和关闭
        private async Task StatusProgressBarShowTaskAnsy(Func<Task> action)
        {
            ContentView.IsEnabled = MenuView.IsEnabled = false;
            StatusProgressBar.Value = 0;
            WorksCancel.Visibility = StatusProgressBar.Visibility = Visibility.Visible;
            await action();
            WorksCancel.Visibility = StatusProgressBar.Visibility = Visibility.Collapsed;
            ContentView.IsEnabled = MenuView.IsEnabled = true;

        }
        private async Task<int> StatusProgressBarShowTaskAnsyInt(Func<Task<int>> action)
        {
            ContentView.IsEnabled = MenuView.IsEnabled = false;
            StatusProgressBar.Value = 0;
            WorksCancel.Visibility = StatusProgressBar.Visibility = Visibility.Visible;
            int result = await action();
            WorksCancel.Visibility = StatusProgressBar.Visibility = Visibility.Collapsed;
            ContentView.IsEnabled = MenuView.IsEnabled = true;
            return result;
        }
        //初始化获取文件枚举模式
        private void GetFileMode_Loaded(object sender, RoutedEventArgs e) => GetFileMode.SelectedIndex = 0;

        //开始搜索
        private int FrontLengthInt => string.IsNullOrEmpty(FrontLength.Text) ? 0 : int.Parse(FrontLength.Text);
        private int AfterLengthInt => string.IsNullOrEmpty(AfterLength.Text) ? 0 : int.Parse(AfterLength.Text);
        private async void StartSearch_Button_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(SearchText.Text))
            {
                MessageBox.Show("请输入搜索内容","无内容警告",MessageBoxButton.OK,MessageBoxImage.Warning);
                return;
            }
            UtilityTools.SetSearchHistory(SearchDirectoryPath.Text);
            ISearcher searcher;
            if (ExpressionButton.IsChecked!.Value)
                searcher = new ExpressionSearcher(SearchText.Text, FrontLengthInt, AfterLengthInt);
            else
                searcher = new StandardSearcher(SearchText.Text, IsAllMatch ,IsCompleteMatch, FrontLengthInt, AfterLengthInt);
            cancellationTokenSource = new CancellationTokenSource();
            int resultCount = await StatusProgressBarShowTaskAnsyInt(() => Search.SearchElementsAsync(searcher, cancellationTokenSource, StatusProgressBar));
            if (!cancellationTokenSource.IsCancellationRequested)
                SearchResults = new ObservableCollection<SearchResult>(searcher.GetResults);
            cancellationTokenSource.Dispose();
            cancellationTokenSource = null;
        }

        //选择搜索根目录
        private void SelectPath_Click(object sender, RoutedEventArgs e)
        {
            using (CommonOpenFileDialog ofd = new())
            {
                ofd.Multiselect = false;
                ofd.Title = "选择搜索路径";
                ofd.DefaultDirectory = Directory.Exists(SearchDirectoryPath.Text) ? SearchDirectoryPath.Text : Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
                ofd.EnsurePathExists = true;
                ofd.InitialDirectory = ofd.DefaultDirectory;
                ofd.IsFolderPicker = true;
                if (ofd.ShowDialog(this) == CommonFileDialogResult.Ok)
                    SearchDirectoryPath.Text = ofd.FileName;
            }
        }

        //搜索历史根目录对话-打开
        private void ShowSearchHistoryView_Button_Click(object sender, RoutedEventArgs e) => SearchHistoryView.Visibility = Visibility.Visible;

        //搜索历史根目录对话-关闭
        private void SearchHistoryView_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (SearchHistoryView.Visibility != Visibility.Hidden)
                SearchHistoryView.Visibility = Visibility.Hidden;
        }

        //搜索历史根目录对话-使用选择的历史项
        private void SearchHistoryView_ListBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            ListBox lb = (ListBox)sender;
            SearchDirectoryPath.Text = (string)lb.SelectedItem;
            SearchHistoryView.Visibility = Visibility.Hidden;
            e.Handled = true;
        }

        //搜索文件类型选择对话-打开
        private void FileTypeSelectViewOpen_Button_Click(object sender, RoutedEventArgs e) => FileTypeSelectView.Visibility = Visibility.Visible;

        //搜索文件类型选择对话-关闭
        private void FileTypeSelectView_Close_Button_Click(object sender, RoutedEventArgs e) => FileTypeSelectView.Visibility = Visibility.Hidden;

        //搜索文件类型选择对话-全部取消
        private void FileTypeSelectAllCancel_Button_Click(object sender, RoutedEventArgs e)
        {
            Config.Instance.AllFileTypes.ForEach(p => p.Enable = false);
            Config.Instance.AllFileTypesUpdate();
        }

        //搜索文件类型选择对话-反选
        private void FileTypeSelectInvertSelection_Button_Click(object sender, RoutedEventArgs e)
        {
            Config.Instance.AllFileTypes.ForEach(p => p.Enable = !p.Enable);
            Config.Instance.AllFileTypesUpdate();
        }

        //搜索文件类型选择对话-移除所选的全部类型(仅限文本类型)
        private void FileTypeSelectRemove_Button_Click(object sender, RoutedEventArgs e)
        {
            var select = Config.Instance.TextFileTypes.Where(p => p.Enable).ToArray();
            if (select.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("确认继续将删除下列扩展格式，确认么?");
                foreach (var item in select)
                    sb.AppendLine(item.TypeExtension);
                if (MessageBox.Show(this, sb.ToString(), "删除确认", MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.OK)
                    select.ForEach(p => Config.Instance.TextFileTypes.Remove(p));
                Config.Save();
            }
            if (Config.Instance.ExtensionFileTypes.Any(p => p.Enable))
                MessageBox.Show(this, "非文本的扩展格式不支持删除");
            Config.Instance.AllFileTypesUpdate();
        }

        //搜索文件类型选择对话-打开新增类型对话
        private void FileTypeSelectAdd_Button_Click(object sender, RoutedEventArgs e) => AddFileTypeView.Visibility = Visibility.Visible;

        //搜索文件类型选择对话-打开新增类型对话-新增(仅限文本类型)
        private void AddFileTypeOK_Button_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(AddFileTypeTextBox.Text))
            {
                MessageBox.Show("请输入文件类型扩展名");
                return;
            }
            if (!AddFileTypeTextBox.Text.StartsWith('.'))
                AddFileTypeTextBox.Text = "." + AddFileTypeTextBox.Text.Trim();
            if (Config.Instance.TextFileTypes.Any(p => p.TypeExtensionEquals(AddFileTypeTextBox.Text)))
            {
                MessageBox.Show("当前文件类型扩展名 已存在!");
                return;
            }
            Config.Instance.TextFileTypes.Add(new Lib.Data.SearchFileType { Enable = false, TypeExtension = AddFileTypeTextBox.Text });
            Config.Save();
            Config.Instance.AllFileTypesUpdate();
            AddFileTypeView.Visibility = Visibility.Hidden;
        }

        //搜索文件类型选择对话-打开新增类型对话-取消添加(关闭对话)
        private void AddFileTypeCancel_Button_Click(object sender, RoutedEventArgs e) => AddFileTypeView.Visibility = Visibility.Hidden;

        //根据文件搜索类型获取文件-并填充列表
        private async void GetFile_Button_Click(object sender, RoutedEventArgs e)
        {
            string RootPath = SearchDirectoryPath.Text;
            FileElements.GetFileModeEnum mode = (FileElements.GetFileModeEnum)GetFileMode.SelectedValue;
            SearchResults.Clear();
            cancellationTokenSource = new CancellationTokenSource();
            await StatusProgressBarShowTaskAnsy(async () => await FileElements.Instance.GetFilesAnsy(RootPath, mode, cancellationTokenSource, StatusProgressBar));
            cancellationTokenSource.Dispose();
            cancellationTokenSource = null;
        }

        //文件列表-设置搜索项-全选
        private void SelectAll_Button_Click(object sender, RoutedEventArgs e) => FileElements.Instance.FileElementCollection.ForEach(p => p.Enable = true);

        //文件列表-设置搜索项-反选
        private void InvertSelect_Button_Click(object sender, RoutedEventArgs e) => FileElements.Instance.FileElementCollection.ForEach(p => p.Enable = !p.Enable);

        //设置编码到选择项
        private void SetEncoding_Button_Click(object sender, RoutedEventArgs e)
        {
            FileElements.Instance.FileElementCollection.ForEach(p =>
            {
                if (p.Enable && p.encodingData != FileElements.NotAvailableEncodingData)
                    p.encodingData = (FileElements.EncodingData)SelectEncoding.SelectedItem;
            });
        }
        //系统IFilter选项-全部设置到禁用状态 
        private void IFilterDisable_Button_Click(object sender, RoutedEventArgs e)
        {
            FileElements.Instance.AllExtensionTypeFile.ForEach(p => p.EnableIFilter = false);
        }
        //系统IFilter选项-设置状态到相反
        private void IFilterInvertSet_Button_Click(object sender, RoutedEventArgs e)
        {
            FileElements.Instance.AllExtensionTypeFile.ForEach(p => p.EnableIFilter = !p.EnableIFilter);
        }

        //取消当前的工作
        private void WorksCancel_Click(object sender, RoutedEventArgs e)
        {
            if (cancellationTokenSource != null)
                cancellationTokenSource.Cancel();
        }
        //替换
        private async void Replace_Button_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("操作将开始替换所有选择的项，是否继续", "替换确认", MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.Cancel)
                return;
            cancellationTokenSource = new CancellationTokenSource();
            await StatusProgressBarShowTaskAnsy(() => 
                SearchResult.ReplaceModify(SearchResults.Where(p => p.IsSelected), SearchText.Text, cancellationTokenSource, 
                    p => StatusProgressBar.Dispatcher.BeginInvoke(() => StatusProgressBar.Value = p)));
            cancellationTokenSource.Dispose();
            cancellationTokenSource = null;

        }
        //搜索结果列表-点击后文件列表选择到对应元素
        private void SearchResult_ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 1)
            {
                FileListBox.SelectedItem = ((SearchResult)e.AddedItems[0]!).FileElement;
                FileListBox.ScrollIntoView(FileListBox.SelectedItem);
            }
        }
        //搜索结果列表-右键-全选
        private void SearchResult_ListBox_AllSelect_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            SearchResults.ForEach(p => p.IsSelected = true);
        }
        //搜索结果列表-右键-反选
        private void SearchResult_ListBox_InvertSelect_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            SearchResults.ForEach(p => p.IsSelected = !p.IsSelected);
        }
        //搜索结果列表-右键-全取消
        private void SearchResult_ListBox_ALLCancelSelect_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            SearchResults.ForEach(p => p.IsSelected = false);
        }
        //搜索结果列表-右键-复制内容
        private void CopyStringToClipboard_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem mi = (MenuItem)sender;
            SearchResult sr = (SearchResult)mi.DataContext;
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(sr.SourceFullInfo);
            sb.AppendLine(sr.PartialContext);
            UtilityTools.CopyStringToClipboard(sb.ToString());
        }

        //文件列表-右键-导航到资源管理器
        private void FileLIst_ListBox_NavigateToExplorer_MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem mi = (MenuItem)sender;
            UtilityTools.ExplorerProcessStart(((FileElements.FileElement)mi.DataContext).Path);
        }
        //文件列表-右键-打开方式
        private void FileLIst_OpenWith_MenuItem_Click(object sender, RoutedEventArgs e) 
        {
            MenuItem mi = (MenuItem)sender;
            UtilityTools.OpenWith(((FileElements.FileElement)mi.DataContext).Path);
        }
        //文件列表-右键-记事本
        private void FileLIst_NotepadOpen_MenuItem_Click(object sender, RoutedEventArgs e) 
        {
            MenuItem mi = (MenuItem)sender;
            UtilityTools.NotepadOpen(((FileElements.FileElement)mi.DataContext).Path);
        }
        //文件列表-右键-默认
        private void FileLIst_DefaultOpen_MenuItem_Click(object sender, RoutedEventArgs e) 
        {
            MenuItem mi = (MenuItem)sender;
            UtilityTools.DefaultOpen(((FileElements.FileElement)mi.DataContext).Path);
        }
        //文件列表-右键-复制所有选择的文件
        private void FileLIst_CopyFileToClipboard_MenuItem_Click(object sender, RoutedEventArgs e) 
        {
            UtilityTools.CopyFileToClipboard(FileElements.Instance.FileElementCollection.Where(p => p.Enable).Select(p => p.Path).ToArray());
        }
        //文件列表-右键-复制所有选择的路径
        private void FileLIst_CopyPathsToClipboard_MenuItem_Click(object sender, RoutedEventArgs e) 
        {
            UtilityTools.CopyPathsToClipboard(FileElements.Instance.FileElementCollection.Where(p => p.Enable).Select(p => p.Path).ToArray());
        }
    }
}
